package com.example.tybei_lalojban_2;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Vibrator;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import com.example.tools.LoadJSON;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;

public class main extends AppCompatActivity {
    private LoadJSON json;
    private JSONObject jsonObject,jsonObject2;
    private List<LoadJSON.gismu> word_list;
    private Map<LoadJSON.gismu, Boolean> known_list;
    private int wordListIt=0,word_counter,word_number;
    private boolean callback=false,enable_fast=false,fast;
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onCreate(Bundle s){
        super.onCreate(s);
        init();
    }
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onActivityResult(int req,int res,Intent i){
        super.onActivityResult(req,res,i);
        if(req==0x000&&res==0x010){
            Bundle b=i.getExtras();
            ArrayList<LoadJSON.gismu> rv=b.getParcelableArrayList("rv");
            word_number+=rv.size();
            word_counter+=rv.size();
            for(LoadJSON.gismu j:rv){
                try {
                    jsonObject2.put(j.name,1);
                    jsonObject.put(j.name,0);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                if(word_list.size()<=wordListIt+1){
                    word_list.add(j);
                }
                else {
                    word_list.add(new Random().nextInt(word_list.size() - wordListIt - 1) + wordListIt + 1, j);
                }
            }
            onBei(word_list.get(wordListIt),false);
        }
        else if(req==0x001&&res==0x011){
            Bundle b=i.getExtras();
            Log.i("info","it:"+wordListIt);
            if(known_list==null) known_list=new HashMap<>();
            if(!known_list.containsKey(word_list.get(wordListIt-1))) {
                if (b.getBoolean("known")) {
                    word_counter--;
                    known_list.put(word_list.get(wordListIt - 1), true);
                    Log.i("known", word_list.get(wordListIt - 1).name);
                } else {
                    word_counter++;
                    Random random = new Random();
                    if(word_list.size()<=wordListIt+1){
                        word_list.add(word_list.size(),word_list.get(wordListIt - 1));
                        word_list.add(word_list.size(),word_list.get(wordListIt - 1));
                    }
                    else{
                        int cache=random.nextInt(word_list.size() - wordListIt - 1) + wordListIt + 1;
                        word_list.add(cache, word_list.get(wordListIt - 1));
                        int cache2;
                        do{
                            cache2=random.nextInt(word_list.size() - wordListIt - 1) + wordListIt + 1;
                        }
                        while(!(word_list.size() <= 3 || cache2 != cache && cache2 != cache + 1));
                        word_list.add(cache2,word_list.get(wordListIt-1));
                    }
                    known_list.put(word_list.get(wordListIt - 1), false);
                }
            }
            else if(!b.getBoolean("known")){
                word_list.add(word_list.size() <= 1 ? word_list.size() : new Random().nextInt(word_list.size() - wordListIt - 1) + wordListIt + 1,word_list.get(wordListIt - 1));
            }
            if(wordListIt>=word_list.size()){
                Log.i("ok","finish bei");
                Log.i("info","word list size:"+word_list.size());
                if(word_number<20){
                    start_choose(20-word_number,true);
                }
                else{
                    try {
                        for(LoadJSON.gismu it:known_list.keySet()){
                            Log.i("ok",it.name);
                            if(Objects.requireNonNull(known_list.get(Objects.requireNonNull(it)))){
                                int cache=jsonObject2.optInt(it.name,1);
                                jsonObject.put(it.name,cache+2);
                                Log.i("info", String.valueOf(cache+2));
                                jsonObject2.put(it.name,cache+2);
                            }
                            else{
                                jsonObject.put(it.name,0);
                                Log.i("info","0");
                                jsonObject2.put(it.name,0);
                            }
                        }
                        JSONArray jsonArray=new JSONArray();
                        jsonArray.put(jsonObject);
                        jsonArray.put(jsonObject2);
                        jsonArray.put(enable_fast);
                        Log.i("info","jsonArray="+jsonArray);
                        File file=new File(getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),"chose.json");
                        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                        bw.write(jsonArray.toString());
                        bw.close();
                    } catch (JSONException | FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (NullPointerException e){
                        e.printStackTrace();
                    }
                    start_all_finish();
                }
            }
            else{
                onBei(word_list.get(wordListIt),false);
            }
        }
    }
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void init(){
        Context context=getApplicationContext();
        try {
            if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                File dir=context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),file;
                word_list=new ArrayList<>();
                json=new LoadJSON();
                json.load(getAssets().open("gismu.json"));
                if (!dir.exists()) {
                    if (!dir.mkdir()) {
                        throw new IOException("cannot read chosen.json");
                    }
                }
                file = new File(dir, "chose.json");
                if (!file.exists()) {
                    if (!file.createNewFile()) {
                        throw new IOException("cannot read chosen.json");
                    }
                    Log.i("ok","ready into choose");
                    jsonObject=new JSONObject();
                    jsonObject2=new JSONObject();
                    start_choose(20,false);
                    return;
                }
                Log.i("ok","finish create files");
                BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
                StringBuilder sb = new StringBuilder();
                String count;
                while ((count = br.readLine()) != null) {
                    sb.append(count);
                }
                br.close();
                Log.i("ok","finish read files");
                System.out.println("test");
                JSONArray jsonArray = new JSONArray(sb.toString());
                Log.i("info","jsonArray="+jsonArray.toString());
                jsonObject = jsonArray.optJSONObject(0);
                jsonObject2 = jsonArray.optJSONObject(1);
                enable_fast = jsonArray.optBoolean(2,false);
                if(jsonObject==null||jsonObject2==null){
                    Log.e("file broken","chosen.json broken!");
                    jsonObject=new JSONObject();
                    jsonObject2=new JSONObject();
                    start_choose(20,false);
                    return;
                }
                List<String> cache = new ArrayList<>();
                for (Iterator<String> it = jsonObject.keys(); it.hasNext(); ) {
                    String word = it.next();
                    int days = jsonObject.getInt(word);
                    if (days == 0) {
                        if (cache.size() < 20) {
                            cache.add(word);
                        }
                    } else {
                        jsonObject.put(word, days - 1);
                    }
                }
                if(cache.size()==0){
                    start_choose(20,true);
                }
                else{
                    word_number=cache.size();
                    word_counter=cache.size();
                    startBei(cache);
                }
            }
            else{
                Toast.makeText(context,"SD卡不存在或不可写", Toast.LENGTH_LONG).show();
            }
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }
    }
    public void startBei(List<String> word) {
        Log.i("info","word list:"+word);
        for(String i:word){
            word_list.add(json.findGismu(i));
        }
        wordListIt=0;
        known_list=new HashMap<>();
        onBei(word_list.get(wordListIt),false);
    }
    public void onBei(LoadJSON.gismu word,boolean is_fast) {
        wordListIt++;
        fast=true;
        setContentView(R.layout.main);
        TextView sentences=findViewById(R.id.sentences),meaning=findViewById(R.id.meaning),last=findViewById(R.id.last);
        Button check=findViewById(R.id.check);
        String meanings="["+word.ciXing+ "] " +word.meaning;
        meaning.setText(meanings);
        String lasts="剩余"+ (word_number + word_counter - word_list.size()) +"词";
        Log.i("info",String.valueOf(word_counter));
        Log.i("info",String.valueOf(word_list.size()));
        Log.i("info",String.valueOf(word_number));
        last.setText(lasts);
        if(is_fast){
            onClickListener(check,word,lasts);
        }
        else{
            StringBuilder sb=new StringBuilder();
            for(Map.Entry<String,String> i:word.sentences.entrySet()){
                String sentence=i.getKey().replace("%", new String(new char[word.name.length()]).replace("\0","_"));
                sb.append(sentence);
                sb.append('\n');
                sb.append(i.getValue());
                sb.append('\n');
            }
            sentences.setText(sb.toString());
            check.setOnClickListener(v -> onClickListener(v,word,lasts));
        }
    }
    public void onClickListener(View v,LoadJSON.gismu word,String lasts){
        v.setVisibility(View.INVISIBLE);
        findViewById(R.id.dwq_03).setVisibility(View.INVISIBLE);
        findViewById(R.id.sentences_scrollView).setVisibility(View.INVISIBLE);
        findViewById(R.id.sentences).setVisibility(View.INVISIBLE);
        findViewById(R.id.input).setVisibility(View.VISIBLE);
        TextView front=findViewById(R.id.sentence_hint_front),back=findViewById(R.id.sentence_hint_back),chinese=findViewById(R.id.chinese);
        if(word.sentences.keySet().isEmpty()){
            word.sentences.put("null%","null");
            Log.e("sentences missing",word.name);
        }
        String target= (String) word.sentences.keySet().toArray()[word.sentences.keySet().size() <= 1 ? 0 : new Random().nextInt(word.sentences.keySet().size() - 1)];
        front.setText(target.substring(0,target.indexOf("%")));
        back.setText(target.substring(target.indexOf("%")+1));
        chinese.setText(word.sentences.get(target));
        chinese.setVisibility(View.VISIBLE);
        EditText editText=findViewById(R.id.enter);
        editText.setTag(false);
        editText.requestFocus();
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public void afterTextChanged(Editable s) {
                if((boolean)editText.getTag()){
                    return ;
                }
                if(callback){
                    callback2();
                }
                editText.setTag(true);
                Log.i("info", String.valueOf(editText.getText().toString().length()));
                Log.v("test", String.valueOf(editText.getText().length()));
                Log.i("info", editText.getText().toString());
                Log.i("info", String.valueOf(editText.getText().toString().length()>=word.name.length()));
                if(editText.getText().toString().length()>=word.name.length()){
                    Log.i("info",String.valueOf(editText.getText().toString().equals(word.name)));
                    Log.i("info",word.name);
                    if(editText.getText().toString().equals(word.name)){
                        if(enable_fast&&fast){
                            if(known_list==null) known_list=new HashMap<>();
                            if(!known_list.containsKey(word_list.get(wordListIt-1))) {
                                word_counter--;
                                known_list.put(word_list.get(wordListIt - 1), true);
                                Log.i("known", word_list.get(wordListIt - 1).name);
                            }
                            if(wordListIt>=word_list.size()){
                                Log.i("ok","finish bei");
                                Log.i("info","word list size:"+word_list.size());
                                if(word_number<20){
                                    start_choose(20-word_number,true);
                                }
                                else{
                                    try {
                                        for(LoadJSON.gismu it:known_list.keySet()){
                                            Log.i("ok",it.name);
                                            if(Objects.requireNonNull(known_list.get(Objects.requireNonNull(it)))){
                                                int cache=jsonObject2.optInt(it.name,1);
                                                jsonObject.put(it.name,cache+2);
                                                Log.i("info", String.valueOf(cache+2));
                                                jsonObject2.put(it.name,cache+2);
                                            }
                                            else{
                                                jsonObject.put(it.name,0);
                                                Log.i("info","0");
                                                jsonObject2.put(it.name,0);
                                            }
                                        }
                                        JSONArray jsonArray=new JSONArray();
                                        jsonArray.put(jsonObject);
                                        jsonArray.put(jsonObject2);
                                        jsonArray.put(enable_fast);
                                        Log.i("info","jsonArray="+jsonArray);
                                        File file=new File(getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),"chose.json");
                                        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                                        bw.write(jsonArray.toString());
                                        bw.close();
                                    } catch (JSONException | FileNotFoundException e) {
                                        e.printStackTrace();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    } catch (NullPointerException e){
                                        e.printStackTrace();
                                    }
                                    start_all_finish();
                                }
                            }
                            else{
                                onBei(word_list.get(wordListIt),true);
                            }
                        }
                        else{
                            start_finish(word,lasts);
                        }
                    }
                    else{
                        fast=false;
                        editText.setText("");
                        findViewById(R.id.wrong).setVisibility(View.VISIBLE);
                        Button showAnswer=findViewById(R.id.see_answer);
                        showAnswer.setVisibility(View.VISIBLE);
                        new Thread(() -> {
                            Vibrator vibrator=(Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
                            if(vibrator.hasVibrator()) {
                                vibrator.vibrate(500);
                            }
                            else{
                                Toast.makeText(getApplicationContext(),"振动器不存在或无法访问",Toast.LENGTH_SHORT).show();
                            }
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            callback1();

                        }).start();
                        showAnswer.setOnClickListener(v1 -> start_finish(word,lasts));
                    }
                }
                editText.setTag(false);
            }
        });
    }
    public void start_choose(int number,boolean need_last){
        ArrayList<LoadJSON.gismu> last = new ArrayList<>();
        if(need_last) {
            Log.i("ok","into start_choose");
            List<String> cache= new ArrayList<>();
            for(Iterator<String> it=jsonObject.keys();it.hasNext();){
                cache.add(it.next());
            }
            Log.i("info", String.valueOf(cache));
            for (LoadJSON.gismu i : json.dictionary) {
                if(!cache.contains(i.name)){
                    last.add(i);
                }
            }
            Log.i("info","dictionary size is"+last.size());
        }
        else{
            Log.i("ok","into start_choose");
            last=(ArrayList<LoadJSON.gismu>)json.dictionary;
            Log.i("info","the length of dictionary is"+last.size());
        }
        Intent i=new Intent(main.this,choose.class);
        Bundle b=new Bundle();
        b.putInt("number",number);
        b.putParcelableArrayList("json",last);
        i.putExtras(b);
        startActivityForResult(i,0x000);
    }
    public void start_finish(LoadJSON.gismu word,String lasts){
        Log.i("ok","into_start_finish");
        Intent i=new Intent(main.this,finish.class);
        Bundle b=new Bundle();
        b.putParcelable("word",word);
        b.putString("lasts",lasts);
        i.putExtras(b);
        startActivityForResult(i,0x001);
    }
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void start_all_finish(){
        setContentView(R.layout.all_finish);
        Switch fast_mode=findViewById(R.id.fast_mode);
        fast_mode.setChecked(enable_fast);
        fast_mode.setOnCheckedChangeListener((buttonView, isChecked) -> {
            JSONArray jsonArray=new JSONArray();
            jsonArray.put(jsonObject);
            jsonArray.put(jsonObject2);
            jsonArray.put(isChecked);
            Log.i("info","jsonArray="+jsonArray);
            File file=new File(getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),"chose.json");
            BufferedWriter bw;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                bw.write(jsonArray.toString());
                bw.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
    public void callback1(){
        callback=true;
    }
    public void callback2(){
        findViewById(R.id.wrong).setVisibility(View.INVISIBLE);
        callback=false;
    }
}
